dojo.provide("uws.drawing.ConnectionHandler");

dojo.declare('uws.drawing.ConnectionHandler',null,{
	/*
		It handles how to construct a connection given two components.
	*/
	clickCount:null,
	shape1:null,
	shape1_surface:null,
	shape1_dir:null,
	
	shape2:null,
	shape2_dir:null,
	
	button_toggle:null,
	
	top_handlers: [],
	bottom_handlers: [],
	right_handlers: [],
	left_handlers: [],
	
	mouse_handler:null,
	temp_line:null,
	connecting:null,
	diagramType:null,
	connectionType:null,
	
	constructor:function(){
		this.clickCount = 0;
		this.top_handlers = [];
		this.bottom_handlers = [];
		this.right_handlers = [];
		this.left_handlers = [];
		this.temp_line = null;
		this.connecting = false;
	},
	connectThis:function(surface,shape,dir, diagramType, connectionType, button){
		this.clickCount++;
		
		if(this.clickCount==1){
			if(!connectionRestrictionsConstants.isAllowable(diagramType, connectionType, shape.declaredClass)){
				writeToStatusBar("The connection isn't allowed");
				this.clickCount=0;
				this.cancelPending();
				return;
			}
			this.connecting = true;
			this.shape1=shape;
			
			this.shape1_surface=surface;
			this.shape1_dir=dir;
			
			this.diagramType = diagramType;
			this.connectionType = connectionType;
			
			var x1,y1,matrix;
			
			matrix = shape.shape_moveable.shape.matrix;
			if(matrix == null) {
				matrix = {
					dx: 0,
					dy: 0
				};
			}
			
			if(dir=="top"){
				x1 = shape.top_con.shape.cx + matrix.dx;
				y1 = shape.top_con.shape.cy + matrix.dy;
			}else if(dir=="bottom"){
				x1 = shape.bottom_con.shape.cx + matrix.dx;
				y1 = shape.bottom_con.shape.cy + matrix.dy;
			}else if(dir=="right"){
				x1 = shape.right_con.shape.cx + matrix.dx;
				y1 = shape.right_con.shape.cy + matrix.dy;
			}else if(dir=="left"){
				x1 = shape.left_con.shape.cx + matrix.dx;
				y1 = shape.left_con.shape.cy + matrix.dy;
			}
			
			this.temp_line = surface.createLine({
				x1:x1,
				y1:y1,
				x2:(x1+1),
				y2:(y1+1)
			}).setStroke("black");
			
			this.mouse_handler = dojo.connect(surface._parent,"onmousemove",null,function(e){
				if(connectionHandler.temp_line!=null){
					connectionHandler.temp_line.setShape({
						x1:x1,
						y1:y1,
						x2:e.layerX,
						y2:e.layerY
					});
				}
			});
		}else if(
			this.clickCount==2 &&
			(this.shape1_surface==surface && 
			this.diagramType == diagramType &&
			this.connectionType == connectionType)
		){
			if(!connectionRestrictionsConstants.isAllowable(diagramType, connectionType, this.shape1.declaredClass, shape.declaredClass)){
				writeToStatusBar("The connection isn't allowed");
				this.cancelPending();
				return;
			}
			
			if(this.shape1==shape && !connectionRestrictionsConstants.allowLoop(diagramType, connectionType)){
				writeToStatusBar("The connection isn't allowed");
				this.cancelPending();
				return;
			}
			
			this.shape2 = shape;
			this.shape2_dir = dir;
			
			dataStore.fetchItemByIdentity({
				identity: this.shape1_surface.id,
				onItem:function(diagram){
					connectionHandler._executeConnection(diagram);
				},
				onError:function(error){
					console.debug(error);
				}
			});
			this.toggleConnectors();		//includes cancelPending();
			if(button) button.set('checked',false);
		}
	},
	cancelPending:function(){
		this.clickCount=0;
		this.shape1=null;
		this.shape1_dir=null;
		this.shape2=null;
		this.shape2_dir=null;
		
		this.mouse_handler=null;
		dojo.disconnect(this.mouse_handler);
		this.connecting = false;
		
		if(this.temp_line!=null) this.temp_line.removeShape();
		this.temp_line = null;
	},
	toggleConnectors:function(diagramType, connectionType, button){
		
		var surface = surfaceManager.getVisibleSurface();
		if(button!=null && button.checked && surface!=null){
			var uws_comp = surface.uws_components;
			
			if(this.clickCount==0){
				if(this.button_toggle!=null && this.button_toggle != button && this.button_toggle.attr){
					try{
						this.button_toggle.set('checked', false);
					}catch(e){console.log("Unknown bug occured.");}
					
					this.cancelPending();
					this.button_toggle = button;
					
					for(var i=0;i<uws_comp.length;i++){
						var comp = uws_comp[i];
						
						comp.top_con.disconnect(this.top_handlers[comp.id]);
						comp.bottom_con.disconnect(this.bottom_handlers[comp.id]);
						comp.right_con.disconnect(this.right_handlers[comp.id]);
						comp.left_con.disconnect(this.left_handlers[comp.id]);
						
						delete(this.top_handlers[comp.id]);
						delete(this.bottom_handlers[comp.id]);
						delete(this.right_handlers[comp.id]);
						delete(this.left_handlers[comp.id]);
					}
				}
				this.button_toggle = button;
			}
			
			if(this.button_toggle != button){
				this.button_toggle.set('checked', false);
				this.cancelPending();
				this.button_toggle = button;
				
				for(var i=0;i<uws_comp.length;i++){
					var comp = uws_comp[i];
					
					comp.top_con.disconnect(this.top_handlers[comp.id]);
					comp.bottom_con.disconnect(this.bottom_handlers[comp.id]);
					comp.right_con.disconnect(this.right_handlers[comp.id]);
					comp.left_con.disconnect(this.left_handlers[comp.id]);
					
					delete(this.top_handlers[comp.id]);
					delete(this.bottom_handlers[comp.id]);
					delete(this.right_handlers[comp.id]);
					delete(this.left_handlers[comp.id]);
				}
			}
			
			for(var i=0;i<uws_comp.length;i++){
				(function(){
					var comp = uws_comp[i];
					
					if(
						comp.top_con != null &&
						comp.bottom_con != null &&
						comp.right_con != null &&
						comp.left_con != null
					){
						comp.connectors_shape_group.moveToFront();
						comp.top_con.setStroke("red").setFill("red").moveToFront();
						comp.bottom_con.setStroke("red").setFill("red").moveToFront();
						comp.right_con.setStroke("red").setFill("red").moveToFront();
						comp.left_con.setStroke("red").setFill("red").moveToFront();
						
						try{
							comp.top_con.getNode().style.cursor="crosshair";
							comp.bottom_con.getNode().style.cursor="crosshair";
							comp.right_con.getNode().style.cursor="crosshair";
							comp.left_con.getNode().style.cursor="crosshair";
						}catch(e){}
						
						connectionHandler.top_handlers[comp.id] = comp.top_con.connect("onclick",null,function(e){
							connectionHandler.connectThis(surface,comp,"top",diagramType, connectionType, button);
						});
						connectionHandler.bottom_handlers[comp.id] = comp.bottom_con.connect("onclick",null,function(e){
							connectionHandler.connectThis(surface,comp,"bottom",diagramType, connectionType, button);
						});
						connectionHandler.right_handlers[comp.id] = comp.right_con.connect("onclick",null,function(e){
							connectionHandler.connectThis(surface,comp,"right", diagramType, connectionType, button);
						});
						connectionHandler.left_handlers[comp.id] = comp.left_con.connect("onclick",null,function(e){
							connectionHandler.connectThis(surface,comp,"left", diagramType, connectionType, button);
						});
					}
				})();
			};
		}else if(surface!=null){
			this.cancelPending();
			var uws_comp = surface.uws_components;
			
			for(var i=0;i<uws_comp.length;i++){
				var comp = uws_comp[i];
				
				if(
					comp.top_con == null ||
					comp.bottom_con == null ||
					comp.right_con == null ||
					comp.left_con == null
				) continue;
				
				comp.connectors_shape_group.moveToBack();
				comp.top_con.setStroke("white").setFill("white").moveToBack();
				comp.bottom_con.setStroke("white").setFill("white").moveToBack();
				comp.right_con.setStroke("white").setFill("white").moveToBack();
				comp.left_con.setStroke("white").setFill("white").moveToBack();
				
				comp.top_con.disconnect(this.top_handlers[comp.id]);
				comp.bottom_con.disconnect(this.bottom_handlers[comp.id]);
				comp.right_con.disconnect(this.right_handlers[comp.id]);
				comp.left_con.disconnect(this.left_handlers[comp.id]);
				
				delete(this.top_handlers[comp.id]);
				delete(this.bottom_handlers[comp.id]);
				delete(this.right_handlers[comp.id]);
				delete(this.left_handlers[comp.id]);
				
				try{
					comp.top_con.getNode().style.cursor="move";
					comp.bottom_con.getNode().style.cursor="move";
					comp.right_con.getNode().style.cursor="move";
					comp.left_con.getNode().style.cursor="move";
				}catch(e){}
			}
		}
	},
	_executeConnection:function(diagram){
		if(this.diagramType == "usecase"){
			if(this.connectionType == "association"){
				var id = connectionManager.newItem("association",this.shape1.id, this.shape1_dir, this.shape2.id, this.shape2_dir,'', '', diagram);
				var comp = new uws.drawing.usecase.Association(
					id, this.shape1_surface,
					this.shape1, this.shape1_dir, 
					this.shape2, this.shape2_dir, ""
				);
				connectionManager.addItem(id, comp);
			}else if(this.connectionType == "dependency"){
				var id = connectionManager.newItem("dependency",this.shape1.id, this.shape1_dir, this.shape2.id, this.shape2_dir, '', '', diagram);
				var comp = new uws.drawing.usecase.Dependency(
					id, this.shape1_surface,
					this.shape1, this.shape1_dir, 
					this.shape2, this.shape2_dir, ""
				);
				connectionManager.addItem(id, comp);
			}else if(this.connectionType == "generalization"){
				var id = connectionManager.newItem("generalization",this.shape1.id, this.shape1_dir, this.shape2.id, this.shape2_dir, '', '', diagram);
				var comp = new uws.drawing.usecase.Generalization(
					id, this.shape1_surface,
					this.shape1, this.shape1_dir, 
					this.shape2, this.shape2_dir, ""
				);
				connectionManager.addItem(id, comp);
			}
		}else if(this.diagramType == "activity"){
			if(this.connectionType == "flow"){
				var id = connectionManager.newItem("flow",this.shape1.id, this.shape1_dir, this.shape2.id, this.shape2_dir, '', '', diagram);
				var comp = new uws.drawing.activity.Flow(
					id, this.shape1_surface,
					this.shape1, this.shape1_dir, 
					this.shape2, this.shape2_dir, ""
				);
				connectionManager.addItem(id, comp);
			}
		}else if(this.diagramType == "classdiagram"){
			if(this.connectionType == "generalization"){
				var id = connectionManager.newItem("generalization2",this.shape1.id, this.shape1_dir, this.shape2.id, this.shape2_dir, '', '', diagram);
				var comp = new uws.drawing.classdiagram.Generalization(
					id, this.shape1_surface,
					this.shape1, this.shape1_dir, 
					this.shape2, this.shape2_dir, ""
				);
				connectionManager.addItem(id, comp);
			}
		}else if(this.diagramType == "sequence"){
			if(this.connectionType == "flow"){
				var id = connectionManager.newItem("flow2",this.shape1.id, this.shape1_dir, this.shape2.id, this.shape2_dir, '', '', diagram);
				var comp = new uws.drawing.sequence.Flow(
					id, this.shape1_surface,
					this.shape1, this.shape1_dir, 
					this.shape2, this.shape2_dir, ""
				);
				connectionManager.addItem(id, comp);
			}else if(this.connectionType == "loop"){
				var id = connectionManager.newItem("loop",this.shape1.id, this.shape1_dir, this.shape2.id, this.shape2_dir, '', '', diagram);
				var comp = new uws.drawing.sequence.Loop(
					id, this.shape1_surface,
					this.shape1, this.shape1_dir, 
					this.shape2, this.shape2_dir, ""
				);
				connectionManager.addItem(id, comp);
			}
		}else if(this.diagramType == "sqlerd"){
			if(this.connectionType == "relationship"){
				var id = connectionManager.newItem("relationship",this.shape1.id, this.shape1_dir, this.shape2.id, this.shape2_dir, '', 'totalParticipation1#Total Paticipation 1#false#false#Boolean#false#|totalParticipation2#Total Paticipation 2#false#false#Boolean#false#|role1#Role 1##false#String##|role2#Role 2##false#String##', diagram);
				var comp = new uws.drawing.sqlerd.Relationship(
					id, this.shape1_surface,
					this.shape1, this.shape1_dir, 
					this.shape2, this.shape2_dir, "",
					'totalParticipation1#Total Paticipation 1#false#false#Boolean#false#|totalParticipation2#Total Paticipation 2#false#false#Boolean#false#|role1#Role 1##false#String##|role2#Role 2##false#String##'
					,1,1
				);
				connectionManager.addItem(id, comp);
			}else if(this.connectionType == "iRelationship"){
				var id = connectionManager.newItem("iRelationship",this.shape1.id, this.shape1_dir, this.shape2.id, this.shape2_dir, '', 'totalParticipation1#Total Paticipation 1#false#false#Boolean#false#|totalParticipation2#Total Paticipation 2#false#false#Boolean#false#|role1#Role 1##false#String##|role2#Role 2##false#String##', diagram);
				var comp = new uws.drawing.sqlerd.IdentifyingRelationship(
					id, this.shape1_surface,
					this.shape1, this.shape1_dir, 
					this.shape2, this.shape2_dir, "",
					'totalParticipation1#Total Paticipation 1#false#false#Boolean#false#|totalParticipation2#Total Paticipation 2#false#false#Boolean#false#|role1#Role 1##false#String##|role2#Role 2##false#String##'
					,1,1
				);
				connectionManager.addItem(id, comp);
			}else if(this.connectionType == "connection"){
				var id = connectionManager.newItem("connection",this.shape1.id, this.shape1_dir, this.shape2.id, this.shape2_dir, '', '', diagram);
				var comp = new uws.drawing.sqlerd.Connection(
					id, this.shape1_surface,
					this.shape1, this.shape1_dir, 
					this.shape2, this.shape2_dir, ""
				);
				connectionManager.addItem(id, comp);
			}
		}
		
		this.toggleConnectors();				//includes cancelPending();
	},
	connectionFromDataStore:function(id, connectionType, shape1, shape1_dir, shape2, shape2_dir, stereotype, custom, cardinality1, cardinality2, surface){
		if(connectionType == "association"){
			var comp = new uws.drawing.usecase.Association(id, surface, shape1, shape1_dir, shape2, shape2_dir, stereotype);
			connectionManager.addItem(id, comp);
		}else if(connectionType == "generalization"){
			var comp = new uws.drawing.usecase.Generalization(id, surface, shape1, shape1_dir, shape2, shape2_dir, stereotype);
			connectionManager.addItem(id, comp);
		}else if(connectionType == "dependency"){
			var comp = new uws.drawing.usecase.Dependency(id, surface, shape1, shape1_dir, shape2, shape2_dir, stereotype);
			connectionManager.addItem(id, comp);
		}else if(connectionType == "flow"){
			var comp = new uws.drawing.activity.Flow(id, surface, shape1, shape1_dir, shape2, shape2_dir, stereotype);
			connectionManager.addItem(id, comp);
		}else if(connectionType == "generalization2"){
			var comp = new uws.drawing.classdiagram.Generalization(id, surface, shape1, shape1_dir, shape2, shape2_dir, stereotype);
			connectionManager.addItem(id, comp);
		}else if(connectionType == "flow2"){
			var comp = new uws.drawing.sequence.Flow(id, surface, shape1, shape1_dir, shape2, shape2_dir, stereotype);
			connectionManager.addItem(id, comp);
		}else if(connectionType == "loop"){
			var comp = new uws.drawing.sequence.Loop(id, surface, shape1, shape1_dir, shape2, shape2_dir, stereotype);
			connectionManager.addItem(id, comp);
		}else if(connectionType == "relationship"){
			var comp = new uws.drawing.sqlerd.Relationship(id, surface, shape1, shape1_dir, shape2, shape2_dir, stereotype, custom, cardinality1, cardinality2);
			connectionManager.addItem(id, comp);
		}else if(connectionType == "iRelationship"){
			var comp = new uws.drawing.sqlerd.IdentifyingRelationship(id, surface, shape1, shape1_dir, shape2, shape2_dir, stereotype, custom, cardinality1, cardinality2);
			connectionManager.addItem(id, comp);
		}else if(connectionType == "connection"){
			var comp = new uws.drawing.sqlerd.Connection(id, surface, shape1, shape1_dir, shape2, shape2_dir, stereotype);
			connectionManager.addItem(id, comp);
		}
	}
});